package cn.labbook.bluetooth.controller;

import cn.labbook.bluetooth.ammeter.algorithm;
import cn.labbook.bluetooth.common.ResultDto;
import cn.labbook.bluetooth.constant.AmmeterConstant;
import cn.labbook.bluetooth.entity.*;
import cn.labbook.bluetooth.entity.wxpay.WXPay;
import cn.labbook.bluetooth.pojo.vo.TencentOrderQueryVO;
import cn.labbook.bluetooth.service.*;
import cn.labbook.bluetooth.service.impl.TransferRecordServiceImpl;
import cn.labbook.bluetooth.util.GenerateIdUtils;
import cn.labbook.bluetooth.util.StringUtils;
import cn.labbook.bluetooth.util.p645.Protocol645;
import cn.labbook.bluetooth.util.p645.Protocol645BuildUtils;
import cn.labbook.bluetooth.util.p645.Protocol645Utils;
import cn.labbook.bluetooth.util.weixin.pay.PayUtil;
import cn.labbook.bluetooth.util.weixin.pay.UUIDHexGenerator;
import cn.labbook.bluetooth.util.weixin.pay.XmlUtil;
import com.baomidou.mybatisplus.core.conditions.Condition;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Controller
@Slf4j
@RequestMapping("/data/handle")
public class DateHandleNewController extends AbstractController {


    private final static String mch_id = "1491927112";

    private final static String key = "&key=zk123sqweqdsadZK9120392018490184";

    private final static String appid = "wxafeeae8c758d838d";

    @Autowired
    private IAmmeterService ammeterService;
    @Autowired
    private ITenantPayService tenantPayService;
    @Autowired
    private IWarnAmmeterService warnAmmeterService;
    @Autowired
    private IAmmeterReadingService ammeterReadingService;
    @Autowired
    private IAdminService adminService;
    @Autowired
    private ITransferRecordService transferRecordService;


    @RequestMapping("copy")
    @ResponseBody
    public ResultDto copy(HttpServletResponse response, HttpServletRequest request, String address) throws Exception {
        Protocol645 build = Protocol645BuildUtils.build(address, (byte) 0x11, new byte[]{0x34, (byte) 0xD3, (byte) 0xFF, 0x37});
        byte[] bytes = Protocol645Utils.toBytes(build);
        String s3 = algorithm.toString(bytes);
        ResultDto resultDto = new ResultDto();
        resultDto.setData("FEFEFEFE".concat(s3));
        return resultDto;
    }

    @RequestMapping({"decrypt"})
    @ResponseBody
    public ResultDto decrypt(HttpServletResponse response, HttpServletRequest request, String code, String key, String ammeterId) throws Exception {
        ResultDto resultDto = new ResultDto();
        byte[] bytes = algorithm.decryptResult(code, "1234567890123456");
        DecryptData decryptData = algorithm.byteToData(bytes);
        log.info("decryptData========================={}", decryptData.toString());
        BigDecimal bigDecimal = new BigDecimal(Double.parseDouble(decryptData.getBalance()));
        decryptData.setBalance(bigDecimal.setScale(2, 4).toString());
        String lastBuy = decryptData.getLastBuy();
        String ratePrice = decryptData.getRatePrice().substring(16, 32);
        System.out.println("lastBuy:" + lastBuy);
        String count = lastBuy.substring(32, 36);
        String copyTime = "20".concat(lastBuy.substring(36, 46));
        String time = "20".concat(decryptData.getTime().substring(0, 6).concat(decryptData.getTime().substring(8, 14)));
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        SimpleDateFormat format1 = new SimpleDateFormat("yyyyMMddHHmm");
        Date parse = format.parse(time);
        Date copyParse = format1.parse(copyTime);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String formats = sdf.format(copyParse);
        decryptData.setVar17(formats);
        Ammeter ammeter = (Ammeter) this.ammeterService.getById(ammeterId);
        AmmeterReading ammeterReading = new AmmeterReading();
        ammeterReading.setReadingTime(parse);
        ammeterReading.setAmmeterId(ammeterId);
        ammeterReading.setElectricityData(decryptData.getElectricityData());
        ammeterReading.setLastBuy(decryptData.getLastBuy());
        String electricityData = decryptData.getElectricityData().substring(41, 48);
        System.out.println("electricityData:" + electricityData);
        double amount = Double.parseDouble(electricityData) / 100.0D;
        ammeterReading.setElectricQuantity(Double.valueOf(amount));
        ammeterReading.setUseQuantity(Double.valueOf(amount - ammeter.getAmount().doubleValue()));
        this.ammeterReadingService.save(ammeterReading);
        ammeter.setAmount(Double.valueOf(amount));
        ammeter.setReadingTime(parse);
        String mark = decryptData.getStatus().substring(12, 13);
        log.info("mark==========>" + mark);
        if (mark.equals("4")) {
            if (Double.parseDouble(decryptData.getBalance()) > 10000.0D) {
                ammeter.setBalance(Double.valueOf(-0.01D));
                decryptData.setBalance("-0.01");
            } else {
                Double bb = Double.valueOf(0.0D - Double.parseDouble(decryptData.getBalance()));
                ammeter.setBalance(bb);
                decryptData.setBalance(bb.toString());
            }
        } else {
            ammeter.setBalance(Double.valueOf(Double.parseDouble(decryptData.getBalance())));
        }
        String substring = decryptData.getStatus().substring(2, 3);
        String substring1 = decryptData.getStatus().substring(6, 7);
        String s = Integer.toBinaryString(Integer.parseInt(substring1));
        String s1 = Integer.toBinaryString(Integer.parseInt(substring));
        if (!s.substring(s.length() - 1, s.length()).equals(s1.substring(s1.length() - 1, s1.length()))) {
            ammeter.setRelayStatus(Integer.valueOf(0));
        } else {
            ammeter.setRelayStatus(Integer.valueOf(1));
        }
        if (ammeterId != null)
            this.ammeterService.updateById(ammeter);
        System.out.println(ratePrice);
        StringBuffer stringBuilder = new StringBuffer(ratePrice.substring(0, 8));
        StringBuffer stringBuilder1 = new StringBuffer(ratePrice.substring(8, 16));
        stringBuilder.insert(4, ".");
        stringBuilder1.insert(4, ".");
        long equation = algorithm.equation(new Date(), parse) / 1000L;
        if (Double.parseDouble(stringBuilder1.toString()) != ammeter.getDayPrice().doubleValue() || Double.parseDouble(stringBuilder.toString()) != ammeter.getNightPrice().doubleValue()) {
            if (equation > 300L || equation < -300L) {
                WarnAmmeter warnAmmeter = new WarnAmmeter();
                warnAmmeter.setAmmeterId(ammeterId);
                warnAmmeter.setGmtCreate(new Date());
                warnAmmeter.setId(GenerateIdUtils.get32Varchar());
                warnAmmeter.setLocation(((Ammeter) this.ammeterService.getById(ammeterId)).getLocation());
                warnAmmeter.setWarnType("重要报警:电表时间不准确");
                this.warnAmmeterService.save(warnAmmeter);
                resultDto.setCode(Integer.valueOf(3));
            } else if (equation > 15L || equation < -15L) {
                resultDto.setCode(Integer.valueOf(3));
            } else {
                resultDto.setCode(Integer.valueOf(2));
            }
        } else if (equation > 10L || equation < -10L) {
            resultDto.setCode(Integer.valueOf(1));
        } else {
            resultDto.setCode(Integer.valueOf(0));
        }
        HttpSession session = request.getSession();
        session.setAttribute("count", count);
        resultDto.setData(decryptData);
        return resultDto;
    }

    @RequestMapping({"factorOne"})
    @ResponseBody
    public ResultDto factorOne(HttpServletResponse response, HttpServletRequest request, String phoneTime, String ammeterTime, String address) throws Exception {
        HttpSession session = request.getSession();
        String complement = algorithm.complement(phoneTime, "34");
        session.setAttribute("time0", ammeterTime);
        System.out.println("TIME1:" + ammeterTime);
        session.setAttribute("time1", complement);
        System.out.println("ammeterTime:" + ammeterTime);
        System.out.println("complement:" + complement);
        String s = algorithm.actorOne(ammeterTime, address);
        System.out.println("key1:" + s);
        String ct = "3236B33A77665544".concat(algorithm.encryptResult(algorithm.toByteArray(complement), s));
        System.out.println("ct:" + ct);
        session.setAttribute("key1", s);
        String ammeterTime1 = algorithm.complement(ammeterTime, "55");
        String address1 = algorithm.complement(address, "55");
        String ss = algorithm.stringPlus(ammeterTime1, address1);
        String s1 = algorithm.byteTrans(ss, 7, 6, 5, 4, 3, 2, 1, 0);
        String s2 = algorithm.stringPlus(s1, "0101010101010101");
        System.out.println("key2:" + s2);
        session.setAttribute("key2", s2);
        System.out.println("SESSION" + session.getAttribute("key2").toString());
        Protocol645 build = Protocol645BuildUtils.build(address, (byte) 3, algorithm.toByteArray(ct));
        byte[] bytes = Protocol645Utils.toBytes(build);
        String s3 = algorithm.toString(bytes);
        System.out.println("TIME:" + s3);
        ResultDto resultDto = new ResultDto();
        resultDto.setData("FEFEFEFE".concat(s3));
        System.out.println("FECT:" + "FEFEFEFE".concat(s3));
        return resultDto;
    }

    @RequestMapping({"factorTwo"})
    @ResponseBody
    public ResultDto factorTwo(HttpServletResponse response, HttpServletRequest request, String ct, String address) throws Exception {
        ResultDto resultDto = new ResultDto();
        HttpSession session = request.getSession();
        Object key1d = session.getAttribute("key1");
        if (Objects.isNull(key1d)) {
            return null;
        }
        byte[] key2s = algorithm.decryptResult(ct, key1d.toString());
        byte[] var = new byte[16];
        System.arraycopy(key2s, 0, var, 0, 16);
        String key2 = session.getAttribute("key2").toString();
        byte[] key1s = algorithm.decrypt(var, session.getAttribute("key2").toString());
        String s = algorithm.toString(key1s);
        String time1 = session.getAttribute("time1").toString();
        if (time1.equals(s)) {
            byte[] var1 = new byte[8];
            System.arraycopy(key2s, 16, var1, 0, 8);
            String s1 = algorithm.toString(var1);
            byte[] key2s1 = algorithm.encrypt(algorithm.toByteArray(s1), session.getAttribute("key2").toString());
            String s2 = algorithm.toString(key2s1);
            String key1 = "3236333A77665544" + algorithm.encryptResult(algorithm.toByteArray(s2), session.getAttribute("key1").toString());
            Protocol645 build = Protocol645BuildUtils.build(address, (byte) 3, algorithm.toByteArray(key1));
            byte[] bytes = Protocol645Utils.toBytes(build);
            String s3 = algorithm.toString(bytes);
            resultDto.setCode(Integer.valueOf(1));
            resultDto.setData("FEFEFEFE".concat(s3));
            return resultDto;
        }
        return null;
    }

    @RequestMapping({"factorThree"})
    @ResponseBody
    public ResultDto factorTwo(HttpServletResponse response, HttpServletRequest request, String ct, String address, String key1, String key2) throws Exception {
        HttpSession session = request.getSession();
        String time11 = session.getAttribute("time0").toString();
        log.info("time11:" + time11);
        String complement = algorithm.complement(time11, "55");
        String skey1 = algorithm.actorTwo(time11, address);
        session.setAttribute("key3", skey1);
        byte[] encrypt = algorithm.encrypt(algorithm.toByteArray(complement), skey1);
        String time = algorithm.getTime();
        System.out.println(time);
        log.info("time:" + time);
        session.setAttribute("time2", time);
        String result = "";
        result = algorithm.toString(encrypt).concat("12").concat(time);
        String skey2 = algorithm.actorThree(time11, address);
        log.info("skey2:" + skey2);
        session.setAttribute("key4", skey2);
        log.info("result:" + result);
        String s1 = algorithm.encryptResult(algorithm.toByteArray(result), skey2);
        log.info("s1:" + s1);
        String s = "3233333A77665544" + algorithm.encryptResult(algorithm.toByteArray(result), skey2);
        log.info("s:" + s);
        Protocol645 build = Protocol645BuildUtils.build(address, (byte) 3, algorithm.toByteArray(s));
        byte[] bytes = Protocol645Utils.toBytes(build);
        String s3 = algorithm.toString(bytes);
        ResultDto resultDto = new ResultDto();
        resultDto.setData("FEFEFEFE".concat(s3));
        resultDto.setCode(Integer.valueOf(1));
        return resultDto;
    }

    @RequestMapping({"factorFour"})
    @ResponseBody
    public ResultDto factorFore(HttpServletResponse response, HttpServletRequest request, String ct, String address, String key1, String key2) throws Exception {
        HttpSession session = request.getSession();
        String key3 = session.getAttribute("key3").toString();
        String key4 = session.getAttribute("key4").toString();
        byte[] bytes = algorithm.decryptResult(ct, key4);
        byte[] decrypt = algorithm.decrypt(bytes, key3);
        String s = algorithm.toString(decrypt);
        String time2 = algorithm.complement(session.getAttribute("time2").toString(), "55");
        String substring1 = s.substring(2, 16);
        String substring2 = time2.substring(2, 16);
        if (substring1.equals(substring2))
            return success();
        return fail();
    }

    @RequestMapping({"pay"})
    @ResponseBody
    public ResultDto pay(HttpServletResponse response, HttpServletRequest request, String address) throws Exception {
        System.out.println("pay");
        HttpSession session = request.getSession();
        String key3 = session.getAttribute("key3").toString();
        String key4 = session.getAttribute("key4").toString();
        ResultDto resultDto = new ResultDto();
        LambdaQueryWrapper<TenantPay> lambda = (new QueryWrapper()).lambda();
        lambda.eq(TenantPay::getIsSynchrony, Integer.valueOf(0));
        lambda.eq(TenantPay::getPayStatus, Integer.valueOf(0));
        lambda.eq(TenantPay::getAmmeterId, address);
        List<TenantPay> list = this.tenantPayService.list((Wrapper) lambda);
        if (list.size() == 0) {
            resultDto.setCode(Integer.valueOf(3));
            return resultDto;
        }
        TenantPay tenantPay = list.get(0);
        Double payAmouont = tenantPay.getPayTrueAmouont();
        if (StringUtils.isBlank(new Object[]{payAmouont})) {
            resultDto.setCode(Integer.valueOf(3));
            return resultDto;
        }

//        TencentOrderQueryVO tencentOrderQueryVO = transferRecordService.orderQuery(tenantPay.getTenantPayId());
//        double totalFeeValue = Double.parseDouble(tencentOrderQueryVO.getCash_fee());
//        double totalAmount = totalFeeValue / 100;
//
//        LambdaQueryWrapper<Ammeter> ammeterLambda = (new QueryWrapper().lambda());
//        Ammeter ammeter = ammeterService.getOne(ammeterLambda);
//
//        if (ammeter.getIsSkimp() == AmmeterConstant.IsSkimp.YES) {
//            log.info("支付金额校验，房客承担服务费");
//            double rate = ammeterService.getNowPrice(ammeter.getAmmeterId());
//            double totalPlatformAmount = payAmouont * rate / 100;
//            if ((payAmouont + totalPlatformAmount) == totalAmount) {
//                log.info("校验通过");
//            } else {
//                log.warn("校验不通过");
//                resultDto.setCode(Integer.valueOf(3));
//                return resultDto;
//            }
//
//        } else {
//            log.info("支付金额校验，房东承担服务费");
//            if (totalAmount == payAmouont) {
//                log.info("校验通过");
//            } else {
//                log.warn("校验不通过");
//                resultDto.setCode(Integer.valueOf(3));
//                return resultDto;
//            }
//        }

        String s2 = payAmouont.toString();
        String[] split = s2.split("\\.");
        String su = split[1];
        if (split[1].length() < 2)
            for (int i = 0; i < 2 - split[1].length(); i++)
                su = su + "0";
        su = split[0] + su;
        System.out.println("COUNTֵ" + session.getAttribute("count").toString());
        String price1 = Integer.toHexString(Integer.parseInt(su));
        String count1 = Integer.toHexString(Integer.parseInt(session.getAttribute("count").toString()) + 1);
        session.setAttribute("count", Integer.valueOf(Integer.parseInt(session.getAttribute("count").toString()) + 1));
        String price = price1;
        String count = count1;
        if (price1.length() < 8)
            for (int i = 0; i < 8 - price1.length(); i++)
                price = "0".concat(price);
        if (count1.length() < 8)
            for (int i = 0; i < 8 - count1.length(); i++)
                count = "0".concat(count);
        String s = price.concat(count);
        byte[] encrypt = algorithm.encrypt(algorithm.toByteArray(s), key3);
        String s1 = "3234343A77665544" + algorithm.encryptResult(encrypt, key4);
        Protocol645 build = Protocol645BuildUtils.build(address, (byte) 3, algorithm.toByteArray(s1));
        byte[] bytes = Protocol645Utils.toBytes(build);
        String s3 = algorithm.toString(bytes);
        Map<String, String> map = new HashMap<>();
        map.put("data", "FEFEFEFE".concat(s3));
        map.put("tenant_pay_id", tenantPay.getTenantPayId());
        resultDto.setData(map);
        if (list.size() > 1) {
            resultDto.setCode(Integer.valueOf(2));
        } else if (list.size() == 1) {
            resultDto.setCode(Integer.valueOf(1));
        }
        return resultDto;
    }

    @RequestMapping({"payReturn"})
    @ResponseBody
    public ResultDto payReturn(HttpServletResponse response, HttpServletRequest request, String tenantPayId) throws Exception {
        TenantPay tenantPay = tenantPayService.getById(tenantPayId);
        tenantPay.setTenantPayId(tenantPayId);
        tenantPay.setIsSynchrony(1);
        boolean b = this.tenantPayService.updateById(tenantPay);
        return b ? success() : fail();
    }

    /**
     * 电表重置
     */
    @RequestMapping({"initialization"})
    @ResponseBody
    public ResultDto initialization(HttpServletRequest request, String address) throws Exception {
        HttpSession session = request.getSession();
        String key3 = session.getAttribute("key3").toString();
        String key4 = session.getAttribute("key4").toString();
        ResultDto resultDto = new ResultDto();
        String s = "0000000000000000";
        byte[] encrypt = algorithm.encrypt(algorithm.toByteArray(s), key3);
        String s1 = "3236343A77665544" + algorithm.encryptResult(encrypt, key4);
        Protocol645 build = Protocol645BuildUtils.build(address, (byte) 3, algorithm.toByteArray(s1));
        byte[] bytes = Protocol645Utils.toBytes(build);
        String s3 = algorithm.toString(bytes);
        Map<String, String> map = new HashMap<>();
        LambdaQueryWrapper<WarnAmmeter> lambda = Condition.lambda();
        lambda.eq(WarnAmmeter::getIsSynchrony, 0);
        lambda.eq(WarnAmmeter::getAmmeterId, address);
        WarnAmmeter one = this.warnAmmeterService.getOne(lambda);
        map.put("data", "FEFEFEFE".concat(s3));

        if (!Objects.isNull(one)) {
            map.put("warn_ammeter_id", one.getId());
        }
        resultDto.setData(map);
        return resultDto;
    }

    @RequestMapping({"initializationReturn"})
    @ResponseBody
    public ResultDto initializationReturn(HttpServletResponse response, HttpServletRequest request, String id) throws Exception {
        WarnAmmeter warnAmmeter = new WarnAmmeter();
        warnAmmeter.setId(id);
        warnAmmeter.setIsSynchrony(Integer.valueOf(1));
        boolean b = this.warnAmmeterService.updateById(warnAmmeter);
        return b ? success() : fail();
    }

    @RequestMapping({"electricPrice"})
    @ResponseBody
    public ResultDto electricPrice(HttpServletRequest request, String address) throws Exception {
        HttpSession session = request.getSession();
        String key3 = session.getAttribute("key3").toString();
        String key4 = session.getAttribute("key4").toString();
        Ammeter ammeter = (Ammeter) this.ammeterService.getById(address);
        Double dayPrice = ammeter.getDayPrice();
        Double nightPrice = ammeter.getNightPrice();
        String s = algorithm.doubleToString(dayPrice);
        String s1 = algorithm.doubleToString(nightPrice);
        String dayPrice1 = s;
        String nightPrice1 = s1;
        if (s.length() < 8)
            for (int i = 0; i < 8 - s.length(); i++)
                dayPrice1 = "0".concat(dayPrice1);
        if (s1.length() < 8)
            for (int i = 0; i < 8 - s1.length(); i++)
                nightPrice1 = "0".concat(nightPrice1);
        String electricPrice = nightPrice1.concat(dayPrice1);
        String electricPrice1 = algorithm.byteTrans(electricPrice, 7, 6, 5, 4, 3, 2, 1, 0);
        String ct = algorithm.encryptResult(algorithm.toByteArray("FF0205040256341244332211" + electricPrice1), key4);
        Protocol645 build = Protocol645BuildUtils.build(address, (byte) 20, algorithm.toByteArray(ct));
        byte[] bytes = Protocol645Utils.toBytes(build);
        String s3 = algorithm.toString(bytes);
        Date effectTime = ammeter.getEffectTime();
        SimpleDateFormat sdf = new SimpleDateFormat("mmHHddMMyy");
        String format = sdf.format(effectTime);
        String ct1 = algorithm.encryptResult(algorithm.toByteArray("080100040256341244332211" + format), key4);
        Protocol645 build1 = Protocol645BuildUtils.build(address, (byte) 20, algorithm.toByteArray(ct1));
        byte[] bytes1 = Protocol645Utils.toBytes(build1);
        String s4 = algorithm.toString(bytes1);
        Map<String, String> map = new HashMap<>();
        ResultDto resultDto = new ResultDto();
        map.put("s3", "FEFEFEFE".concat(s3));
        map.put("s4", "FEFEFEFE".concat(s4));
        resultDto.setData(map);
        return resultDto;
    }

    @RequestMapping({"clockSynchrony"})
    @ResponseBody
    public ResultDto clockSynchrony(HttpServletRequest request, String address) throws Exception {
        HttpSession session = request.getSession();
        String key4 = session.getAttribute("key4").toString();
        String time = algorithm.getTimeBack();
        String ct = algorithm.encryptResult(algorithm.toByteArray("0C0100040256341244332211" + time), key4);
        Protocol645 build = Protocol645BuildUtils.build(address, (byte) 20, algorithm.toByteArray(ct));
        byte[] bytes = Protocol645Utils.toBytes(build);
        String s3 = algorithm.toString(bytes);
        ResultDto resultDto = new ResultDto();
        resultDto.setData("FEFEFEFE".concat(s3));
        resultDto.setCode(Integer.valueOf(1));
        return resultDto;
    }
}
